package org.jeecg.modules.analysis.genealogy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.analysis.genealogy.entity.*;

import org.jeecg.modules.analysis.genealogy.service.IPatentGraphService;
import org.jeecg.modules.demo.patent.entity.Patent;
import org.jeecg.modules.demo.patent.mapper.PatentMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 专利谱系图服务实现
 * @Author: jeecg-boot
 * @Date: 2025-10-11
 * @Version: V1.0
 */
@Service
@Slf4j
public class PatentGraphServiceImpl implements IPatentGraphService {

    @Autowired
    private PatentMapper patentMapper;

    // 基准年份：1900年
    private static final int BASE_YEAR = 1900;

    @Override
    public PatentGraphData getPatentGraphData(String patentId, String relationType) {
        log.info("获取专利谱系图数据，专利ID: {}, 关联类型: {}", patentId, relationType);

        PatentGraphData graphData = new PatentGraphData();
        List<PatentGraphNode> nodes = new ArrayList<>();
        List<PatentGraphLink> links = new ArrayList<>();

        // 查询中心专利
        Patent centerPatent = patentMapper.selectById(patentId);
        if (centerPatent == null) {
            log.error("未找到专利ID: {}", patentId);
            return graphData;
        }

        // 创建中心节点
        PatentGraphNode centerNode = createPatentNode(centerPatent, true);
        nodes.add(centerNode);

        // 根据关联类型获取相关专利
        List<Patent> relatedPatents = new ArrayList<>();
        Set<String> relatedKeys = new HashSet<>();

        if ("institution".equals(relationType)) {
            // 按申请机构关联
            relatedKeys = parseNames(centerPatent.getApplyInstitutionZhName(), centerPatent.getApplyInstitutionOriginName());
            if (!relatedKeys.isEmpty()) {
                relatedPatents = getPatentsByInstitution(relatedKeys, patentId);
            }

            // 为每个关联的机构创建节点
            for (String instName : relatedKeys) {
                PatentGraphNode instNode = new PatentGraphNode();
                instNode.setId("inst_" + instName.hashCode());
                instNode.setName(instName);
                instNode.setType("institution");
                instNode.setCategory(1);

                // 计算该机构的专利数量
                int patentCount = getPatentCountByInstitution(instName);
                instNode.setValue((double) patentCount);

                PatentNodeDetail detail = new PatentNodeDetail();
                detail.setApplyInstitutionZhName(instName);
                detail.setPatentCount(patentCount);
                instNode.setDetail(detail);

                nodes.add(instNode);

                // 创建中心节点到机构节点的连接
                PatentGraphLink link = new PatentGraphLink();
                link.setSource(centerNode.getId());
                link.setTarget(instNode.getId());
                link.setRelationType("institution");
                link.setWeight(1.0);
                links.add(link);
            }

        } else if ("inventor".equals(relationType)) {
            // 按发明人关联
            relatedKeys = parseNames(centerPatent.getInventorZhName(), centerPatent.getInventorOriginName());
            if (!relatedKeys.isEmpty()) {
                relatedPatents = getPatentsByInventor(relatedKeys, patentId);
            }

            // 为每个关联的发明人创建节点
            for (String inventorName : relatedKeys) {
                PatentGraphNode inventorNode = new PatentGraphNode();
                inventorNode.setId("inventor_" + inventorName.hashCode());
                inventorNode.setName(inventorName);
                inventorNode.setType("inventor");
                inventorNode.setCategory(2);

                // 计算该发明人的专利数量
                int patentCount = getPatentCountByInventor(inventorName);
                inventorNode.setValue((double) patentCount);

                PatentNodeDetail detail = new PatentNodeDetail();
                detail.setInventorZhName(inventorName);
                detail.setPatentCount(patentCount);
                inventorNode.setDetail(detail);

                nodes.add(inventorNode);

                // 创建中心节点到发明人节点的连接
                PatentGraphLink link = new PatentGraphLink();
                link.setSource(centerNode.getId());
                link.setTarget(inventorNode.getId());
                link.setRelationType("inventor");
                link.setWeight(1.0);
                links.add(link);
            }
        }

        // 为相关专利创建节点（限制数量避免图形过于复杂）
        int maxRelatedPatents = 20;
        List<Patent> limitedPatents = relatedPatents.stream()
                .limit(maxRelatedPatents)
                .collect(Collectors.toList());

        for (Patent patent : limitedPatents) {
            PatentGraphNode node = createPatentNode(patent, false);
            nodes.add(node);

            // 创建连接关系
            if ("institution".equals(relationType)) {
                Set<String> patentInsts = parseNames(patent.getApplyInstitutionZhName(), patent.getApplyInstitutionOriginName());
                for (String instName : patentInsts) {
                    if (relatedKeys.contains(instName)) {
                        PatentGraphLink link = new PatentGraphLink();
                        link.setSource("inst_" + instName.hashCode());
                        link.setTarget(node.getId());
                        link.setRelationType("institution");
                        link.setWeight(0.5);
                        links.add(link);
                    }
                }
            } else if ("inventor".equals(relationType)) {
                Set<String> patentInventors = parseNames(patent.getInventorZhName(), patent.getInventorOriginName());
                for (String inventorName : patentInventors) {
                    if (relatedKeys.contains(inventorName)) {
                        PatentGraphLink link = new PatentGraphLink();
                        link.setSource("inventor_" + inventorName.hashCode());
                        link.setTarget(node.getId());
                        link.setRelationType("inventor");
                        link.setWeight(0.5);
                        links.add(link);
                    }
                }
            }
        }

        // 设置类别
        List<GraphCategory> categories = new ArrayList<>();
        GraphCategory cat0 = new GraphCategory();
        cat0.setName("中心专利");
        cat0.setSymbol("circle");
        categories.add(cat0);

        GraphCategory cat1 = new GraphCategory();
        cat1.setName("申请机构");
        cat1.setSymbol("rect");
        categories.add(cat1);

        GraphCategory cat2 = new GraphCategory();
        cat2.setName("发明人");
        cat2.setSymbol("triangle");
        categories.add(cat2);

        GraphCategory cat3 = new GraphCategory();
        cat3.setName("相关专利");
        cat3.setSymbol("circle");
        categories.add(cat3);

        graphData.setNodes(nodes);
        graphData.setLinks(links);
        graphData.setCategories(categories);
        graphData.setCenterNodeId(centerNode.getId());
        graphData.setRelationType(relationType);

        log.info("专利谱系图数据生成完成，节点数: {}, 边数: {}", nodes.size(), links.size());
        return graphData;
    }

    @Override
    public Double calculatePatentImportance(String patentId) {
        log.info("计算专利重要性评分，专利ID: {}", patentId);

        Patent patent = patentMapper.selectById(patentId);
        if (patent == null) {
            return 0.0;
        }

        double score = 0.0;

        // 1. 申请机构得分 (权重0.3)
        Set<String> institutions = parseNames(patent.getApplyInstitutionZhName(), patent.getApplyInstitutionOriginName());
        if (!institutions.isEmpty()) {
            int maxInstitutionCount = getMaxPatentCountByInstitution();
            int currentMaxCount = 0;
            for (String inst : institutions) {
                int count = getPatentCountByInstitution(inst);
                currentMaxCount = Math.max(currentMaxCount, count);
            }

            if (maxInstitutionCount > 0) {
                score += (double) currentMaxCount / maxInstitutionCount * 0.3;
            }
        }

        // 2. 发明人得分 (权重0.3)
        Set<String> inventors = parseNames(patent.getInventorZhName(), patent.getInventorOriginName());
        if (!inventors.isEmpty()) {
            int maxInventorCount = getMaxPatentCountByInventor();
            int currentMaxCount = 0;
            for (String inventor : inventors) {
                int count = getPatentCountByInventor(inventor);
                currentMaxCount = Math.max(currentMaxCount, count);
            }

            if (maxInventorCount > 0) {
                score += (double) currentMaxCount / maxInventorCount * 0.3;
            }
        }

        // 3. 申请日期得分 (权重0.4)
        if (patent.getApplyDate() != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(patent.getApplyDate());
            int patentYear = calendar.get(Calendar.YEAR);

            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            int totalRange = currentYear - BASE_YEAR;
            int patentRange = patentYear - BASE_YEAR;

            if (totalRange > 0) {
                score += (double) patentRange / totalRange * 0.4;
            }
        }

        log.info("专利 {} 的重要性评分: {}", patentId, score);
        return score;
    }

    @Override
    public PatentNodeDetail getPatentDetail(String patentId) {
        log.info("获取专利详细信息，专利ID: {}", patentId);

        Patent patent = patentMapper.selectById(patentId);
        if (patent == null) {
            return null;
        }

        PatentNodeDetail detail = new PatentNodeDetail();
        BeanUtils.copyProperties(patent, detail);

        // 计算重要性评分
        detail.setImportance(calculatePatentImportance(patentId));

        return detail;
    }

    /**
     * 创建专利节点
     */
    private PatentGraphNode createPatentNode(Patent patent, boolean isCenter) {
        PatentGraphNode node = new PatentGraphNode();
        node.setId(patent.getId());
        node.setName(patent.getZhName() != null ? patent.getZhName() : patent.getOriginName());
        node.setType("patent");
        node.setCategory(isCenter ? 0 : 3);

        // 计算重要性评分
        Double importance = calculatePatentImportance(patent.getId());
        node.setImportance(importance);
        node.setValue(importance * 100); // 用于控制节点大小

        // 设置详细信息
        PatentNodeDetail detail = new PatentNodeDetail();
        BeanUtils.copyProperties(patent, detail);
        detail.setImportance(importance);
        node.setDetail(detail);

        return node;
    }

    /**
     * 解析名称字符串（可能包含多个名称，用分号或逗号分隔）
     */
    private Set<String> parseNames(String... names) {
        Set<String> result = new HashSet<>();
        for (String name : names) {
            if (name != null && !name.trim().isEmpty()) {
                // 按分号或逗号分隔
                String[] parts = name.split("[;；,，]");
                for (String part : parts) {
                    String trimmed = part.trim();
                    if (!trimmed.isEmpty()) {
                        result.add(trimmed);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 根据申请机构获取专利列表
     */
    private List<Patent> getPatentsByInstitution(Set<String> institutions, String excludePatentId) {
        if (institutions.isEmpty()) {
            return new ArrayList<>();
        }

        QueryWrapper<Patent> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> {
            for (String inst : institutions) {
                wrapper.or(w -> w.like("apply_institution_zh_name", inst))
                       .or(w -> w.like("apply_institution_origin_name", inst));
            }
        });
        queryWrapper.ne("id", excludePatentId);
        queryWrapper.orderByDesc("apply_date");

        return patentMapper.selectList(queryWrapper);
    }

    /**
     * 根据发明人获取专利列表
     */
    private List<Patent> getPatentsByInventor(Set<String> inventors, String excludePatentId) {
        if (inventors.isEmpty()) {
            return new ArrayList<>();
        }

        QueryWrapper<Patent> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> {
            for (String inventor : inventors) {
                wrapper.or(w -> w.like("inventor_zh_name", inventor))
                       .or(w -> w.like("inventor_origin_name", inventor));
            }
        });
        queryWrapper.ne("id", excludePatentId);
        queryWrapper.orderByDesc("apply_date");

        return patentMapper.selectList(queryWrapper);
    }

    /**
     * 获取指定机构的专利数量
     */
    private int getPatentCountByInstitution(String institution) {
        QueryWrapper<Patent> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper ->
            wrapper.like("apply_institution_zh_name", institution)
                   .or()
                   .like("apply_institution_origin_name", institution)
        );
        return patentMapper.selectCount(queryWrapper).intValue();
    }

    /**
     * 获取指定发明人的专利数量
     */
    private int getPatentCountByInventor(String inventor) {
        QueryWrapper<Patent> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper ->
            wrapper.like("inventor_zh_name", inventor)
                   .or()
                   .like("inventor_origin_name", inventor)
        );
        return patentMapper.selectCount(queryWrapper).intValue();
    }

    /**
     * 获取所有机构中专利数量最多的
     */
    private int getMaxPatentCountByInstitution() {
        // 简化实现：查询所有专利，统计机构出现次数
        // 实际生产环境可以使用缓存优化
        List<Patent> allPatents = patentMapper.selectList(null);
        Map<String, Integer> institutionCounts = new HashMap<>();

        for (Patent patent : allPatents) {
            Set<String> institutions = parseNames(patent.getApplyInstitutionZhName(), patent.getApplyInstitutionOriginName());
            for (String inst : institutions) {
                institutionCounts.put(inst, institutionCounts.getOrDefault(inst, 0) + 1);
            }
        }

        return institutionCounts.values().stream().max(Integer::compare).orElse(1);
    }

    /**
     * 获取所有发明人中专利数量最多的
     */
    private int getMaxPatentCountByInventor() {
        // 简化实现：查询所有专利，统计发明人出现次数
        // 实际生产环境可以使用缓存优化
        List<Patent> allPatents = patentMapper.selectList(null);
        Map<String, Integer> inventorCounts = new HashMap<>();

        for (Patent patent : allPatents) {
            Set<String> inventors = parseNames(patent.getInventorZhName(), patent.getInventorOriginName());
            for (String inventor : inventors) {
                inventorCounts.put(inventor, inventorCounts.getOrDefault(inventor, 0) + 1);
            }
        }

        return inventorCounts.values().stream().max(Integer::compare).orElse(1);
    }
}


